From ecaf55d2907835cd0580903e134cdf08416ff694 Mon Sep 17 00:00:00 2001
From: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Date: Tue, 15 Sep 2015 10:27:19 -0500
Subject: [PATCH 208/226] staging: fsl-dpaa2: mac: Added MAC / PHY interface
 driver

This is a commit of the cummulative, squashed dpmac patches.
All the commit logs are preserved below.

Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>

--------------------------------------------------------------

flib,dpmac: add dpmac files (Rebasing onto kernel 3.19, MC 0.6)

patches moved from 4.0 kernel

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
[Stuart: cherry-picked patch and split it up]
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>

staging: fsl-dpaa2: mac: Added MAC / PHY interface driver.

This driver works as a proxy between phylib including phy drivers and
the MC firmware.  It receives updates on link state changes from PHY
lib and forwards them to MC and receives interrupt from MC whenever
a request is made to change the link state.

Signed-off-by: Alex Marginean <alexandru.marginean@freescale.com>
Change-Id: I8097ea69ea8effded3bddd43b9d326bbb59ba6c8
Reviewed-on: http://git.am.freescale.net:8181/35113
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

fsl-dpaa2: mac: Change IRQ flags

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: Ia86570858f9cf7f673089cd7c2078662d56b2f01
Reviewed-on: http://git.am.freescale.net:8181/35581
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

fsl-dpaa2: mac: Check for actual link state change

Do not invoke the MC firmware if the link state hasn't changed.

Signed-off-by: Alex Marginean <alexandru.marginean@freescale.com>
Change-Id: Iba59d8b52c72334efa28f6126e50ec821c802852
Reviewed-on: http://git.am.freescale.net:8181/35582
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

fsl-dpaa2: mac: Fix "dpmac netdevs" probing

Fixup code under DPAA2_MAC_NETDEVS to probe again. In particular, remove
the temporary addition of "fixed.c" in the mac/ folder.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: Iea6768f3c5cd9b2de2c8421c03ecebf155b9792b
Reviewed-on: http://git.am.freescale.net:8181/37673
Reviewed-by: Ruxandra Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
Tested-by: Stuart Yoder <stuart.yoder@freescale.com>

flib: Remove duplicate header files

These files are included by the DPAA2 mac driver files.

Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
Change-Id: Ieff56e3c34393ef65a5ac1123aaf00bacefa050c
Reviewed-on: http://git.am.freescale.net:8181/37257
Reviewed-by: Alexandru Marginean <Alexandru.Marginean@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
Tested-by: Stuart Yoder <stuart.yoder@freescale.com>

fsl-dpaa2: mac: Add dependency on CONFIG_FIXED_PHY

The DPAA2 DPMAC driver currently relies on fixed links, so it will fail
to probe in unusual ways if CONFIG_FIXED_PHY is not enabled.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: Ibc53226a215ed85a2ba22c55b18595fb939e7418
Reviewed-on: http://git.am.freescale.net:8181/37687
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

fsl-dpaa2: mac: Fix macro

Remove macro ending backslash.

Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
Change-Id: Ib0c4a41eee8fbe4aa7c991fc7fdb87771d3bf594
Reviewed-on: http://git.am.freescale.net:8181/37254
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Alexandru Marginean <Alexandru.Marginean@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

fsl-dpaa2: mac: migrated remaining flibs for MC fw 8.0.0

Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
[Stuart: split mac part out of original patch, updated subject]
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>

staging: fsl-dpaa2: mac: Port to MC-0.7 Flibs

Change-Id: Ief731e245bdc207f1bf8e7ff4dfdabb445d6010e
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Reviewed-on: http://git.am.freescale.net:8181/39151
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
Tested-by: Stuart Yoder <stuart.yoder@freescale.com>

staging: fsl-dpaa2: mac: Do programing of MSIs in devm_request_threaded_irq()

With the new dprc_set_obj_irq() we can now program MSIS in the device
in the callback invoked from devm_request_threaded_irq().
Since this callback is invoked with interrupts disabled, we need to
use an atomic portal, instead of the root DPRC's built-in portal
which is non-atomic.

Signed-off-by: Itai Katz <itai.katz@freescale.com>
Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
[Stuart: split original patch up by component]
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>

fsl-dpaa2: mac: Fix driver probing

The DPMAC probing function was broken in many ways. This patch adds
the following fixes:
 - Look up PHY nodes based on the phy-handle property of the respective
   DPMAC node;
 - Defer DPMAC device probing until the MDIO MUX driver probes first (we
   depend on that for configuring the PHYs on PCIe riser cards on
   LS2085A QDS boards.
 - Add Kconfig dependencies on XGMAC_MDIO and MDIO_BUS_MUX_MMIOREG.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

fsl-dpaa2: mac: Fix interrupt handling

The DPMAC has two interrupt events muxed on a single interrupt line.
Both the PHY and the DPNI can initiate a link event.

When the link event is initiated by the PHY (possibly as the effect of an
earlier link change request initiated by a DPNI), we must make sure
dpmac_set_link_state() is explicitly called in order for the event to be
propagated (back) to the DPNI.

Finally, DPMAC interrupt mask has to be explicitly specified before calling
dpmac_set_irq_enabled().

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

fsl-dpaa2: mac: Fix print in case device is not initialized

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

fsl-dpaa2: mac: Fix error paths at probe

Merge error condition checks. Add error codes to the early exit paths.
Fix swapped goto labels.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

fsl-dpaa2: mac: Remove unused function prototype

fixed_phy_register_2() was a leftover since we had to backport fixed PHY
implementation on kernel v3.10.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

fsl-dpaa2/mac: Update dpmac binary interface to v3.2

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

fsl-dpaa2: mac: Update Flib to MC 0.8.1

In practice, this adds a counter for "good" egress frames.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: Add counter for "good" egress frames

Now available with the 0.8.1 Flibs.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: Update dpmac_set_link_state() error checking

As of 0.8.1 Flibs, dpmac_set_link_state() no longer returns what we'd
consider spurious errors. This allows for cleaner error checking on
DPMAC-side.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: Remove __cold attribute

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: Check DPMAC FLIB version

Make sure we support the DPMAC version, otherwise abort probing
early on and provide an error message.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

fsl-dpaa2: mac: Replace uintX_t with uX

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: Fix crash on error path

If the fixed-phy cannot be correctly registered, unregister_netdev()
receives a non-NULL, yet invalid phydev. Force the phydev reference to
NULL to avoid a crash on the probe routine's error path.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: Remove TODOs comments from the code

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: Fix ppx_eth_iface_mode order

ppx_eth_iface_mode must be kept in sync with enum dpmac_eth_if, but some
array values weren't in the right order.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: Remove forward declarations of functions

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: Remove ppx_{err,warn,info} macros

Replace with their straighforward equivalents, their contexts being
non-ambiguous.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: Use non-atomic MC portal

The DPMAC driver does not make MC calls from atomic contexts, so it is
safe to request non-atomic MC portals.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: Replace "ppx" prefix with "dpaa2_mac"

Use a similar naming convention as for the Ethernet driver,
replacing "ppx" with "dpaa2_mac" as prefix for functions and
structures.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>

fsl-dpaa2: mac: Remove unnecessary blank line

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>

fsl-dpaa2: mac: Do not handle link change confirmation interrupt

The need for that interrupt is more about debugging.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: mac: resolve compile issues on uprev to 4.5

-interrupt info in mc struct changed upstream
-fixed_phy_register() had new argument

Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
---
 MAINTAINERS                               |    6 +
 drivers/staging/fsl-dpaa2/Kconfig         |    1 +
 drivers/staging/fsl-dpaa2/Makefile        |    1 +
 drivers/staging/fsl-dpaa2/mac/Kconfig     |   24 +
 drivers/staging/fsl-dpaa2/mac/Makefile    |   10 +
 drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h |  195 ++++++++
 drivers/staging/fsl-dpaa2/mac/dpmac.c     |  422 ++++++++++++++++
 drivers/staging/fsl-dpaa2/mac/dpmac.h     |  593 ++++++++++++++++++++++
 drivers/staging/fsl-dpaa2/mac/mac.c       |  767 +++++++++++++++++++++++++++++
 9 files changed, 2019 insertions(+)
 create mode 100644 drivers/staging/fsl-dpaa2/mac/Kconfig
 create mode 100644 drivers/staging/fsl-dpaa2/mac/Makefile
 create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h
 create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.c
 create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.h
 create mode 100644 drivers/staging/fsl-dpaa2/mac/mac.c

--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4554,6 +4554,12 @@ S:	Maintained
 F:	drivers/staging/fsl-mc/bus/mc-ioctl.h
 F:	drivers/staging/fsl-mc/bus/mc-restool.c
 
+FREESCALE DPAA2 MAC/PHY INTERFACE DRIVER
+M:	Alex Marginean <Alexandru.Marginean@freescale.com>
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+F:	drivers/staging/fsl-dpaa2/mac/
+
 FREEVXFS FILESYSTEM
 M:	Christoph Hellwig <hch@infradead.org>
 W:	ftp://ftp.openlinux.org/pub/people/hch/vxfs
--- a/drivers/staging/fsl-dpaa2/Kconfig
+++ b/drivers/staging/fsl-dpaa2/Kconfig
@@ -9,3 +9,4 @@ config FSL_DPAA2
 	  Build drivers for Freescale DataPath Acceleration Architecture (DPAA2) family of SoCs.
 # TODO move DPIO driver in-here?
 source "drivers/staging/fsl-dpaa2/ethernet/Kconfig"
+source "drivers/staging/fsl-dpaa2/mac/Kconfig"
--- a/drivers/staging/fsl-dpaa2/Makefile
+++ b/drivers/staging/fsl-dpaa2/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_FSL_DPAA2_ETH)	+= ethernet/
+obj-$(CONFIG_FSL_DPAA2_MAC)	+= mac/
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/mac/Kconfig
@@ -0,0 +1,24 @@
+config FSL_DPAA2_MAC
+	tristate "DPAA2 MAC / PHY interface"
+	depends on FSL_MC_BUS && FSL_DPAA2
+	select MDIO_BUS_MUX_MMIOREG
+	select FSL_XGMAC_MDIO
+	select FIXED_PHY
+	---help---
+	Prototype driver for DPAA2 MAC / PHY interface object.
+	This driver works as a proxy between phylib including phy drivers and
+	the MC firmware.  It receives updates on link state changes from PHY
+	lib and forwards them to MC and receives interrupt from MC whenever
+	a request is made to change the link state.
+
+
+config FSL_DPAA2_MAC_NETDEVS
+	bool "Expose net interfaces for PHYs"
+	default n
+	depends on FSL_DPAA2_MAC
+	---help---
+	Exposes macX net interfaces which allow direct control over MACs and
+	PHYs.
+	.
+	Leave disabled if unsure.
+
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/mac/Makefile
@@ -0,0 +1,10 @@
+
+obj-$(CONFIG_FSL_DPAA2_MAC) += dpaa2-mac.o
+
+dpaa2-mac-objs := mac.o dpmac.o
+
+all:
+	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
+
+clean:
+	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h
@@ -0,0 +1,195 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _FSL_DPMAC_CMD_H
+#define _FSL_DPMAC_CMD_H
+
+/* DPMAC Version */
+#define DPMAC_VER_MAJOR				3
+#define DPMAC_VER_MINOR				2
+
+/* Command IDs */
+#define DPMAC_CMDID_CLOSE			0x800
+#define DPMAC_CMDID_OPEN			0x80c
+#define DPMAC_CMDID_CREATE			0x90c
+#define DPMAC_CMDID_DESTROY			0x900
+
+#define DPMAC_CMDID_GET_ATTR			0x004
+#define DPMAC_CMDID_RESET			0x005
+
+#define DPMAC_CMDID_SET_IRQ			0x010
+#define DPMAC_CMDID_GET_IRQ			0x011
+#define DPMAC_CMDID_SET_IRQ_ENABLE		0x012
+#define DPMAC_CMDID_GET_IRQ_ENABLE		0x013
+#define DPMAC_CMDID_SET_IRQ_MASK		0x014
+#define DPMAC_CMDID_GET_IRQ_MASK		0x015
+#define DPMAC_CMDID_GET_IRQ_STATUS		0x016
+#define DPMAC_CMDID_CLEAR_IRQ_STATUS		0x017
+
+#define DPMAC_CMDID_MDIO_READ			0x0c0
+#define DPMAC_CMDID_MDIO_WRITE			0x0c1
+#define DPMAC_CMDID_GET_LINK_CFG		0x0c2
+#define DPMAC_CMDID_SET_LINK_STATE		0x0c3
+#define DPMAC_CMDID_GET_COUNTER			0x0c4
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_CREATE(cmd, cfg) \
+	MC_CMD_OP(cmd, 0, 0,  32, int,      cfg->mac_id)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_OPEN(cmd, dpmac_id) \
+	MC_CMD_OP(cmd, 0, 0,  32, int,	    dpmac_id)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  irq_index);\
+	MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, irq_cfg->addr); \
+	MC_CMD_OP(cmd, 2, 0,  32, int,	    irq_cfg->irq_num); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_GET_IRQ(cmd, irq_index) \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_RSP_GET_IRQ(cmd, type, irq_cfg) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  32, uint32_t, irq_cfg->val); \
+	MC_RSP_OP(cmd, 1, 0,  64, uint64_t, irq_cfg->addr); \
+	MC_RSP_OP(cmd, 2, 0,  32, int,	    irq_cfg->irq_num); \
+	MC_RSP_OP(cmd, 2, 32, 32, int,	    type); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  en); \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_GET_IRQ_ENABLE(cmd, irq_index) \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_RSP_GET_IRQ_ENABLE(cmd, en) \
+	MC_RSP_OP(cmd, 0, 0,  8,  uint8_t,  en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  32, uint32_t, mask);\
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_GET_IRQ_MASK(cmd, irq_index) \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_RSP_GET_IRQ_MASK(cmd, mask) \
+	MC_RSP_OP(cmd, 0, 0,  32, uint32_t, mask)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  32, uint32_t, status);\
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_RSP_GET_IRQ_STATUS(cmd, status) \
+	MC_RSP_OP(cmd, 0, 0,  32, uint32_t, status)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  32, uint32_t, status); \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
+} while (0)
+
+/*                cmd, param, offset, width, type,	arg_name */
+#define DPMAC_RSP_GET_ATTRIBUTES(cmd, attr) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  32, int,			attr->phy_id);\
+	MC_RSP_OP(cmd, 0, 32, 32, int,			attr->id);\
+	MC_RSP_OP(cmd, 1, 0,  16, uint16_t,		attr->version.major);\
+	MC_RSP_OP(cmd, 1, 16, 16, uint16_t,		attr->version.minor);\
+	MC_RSP_OP(cmd, 1, 32,  8, enum dpmac_link_type,	attr->link_type);\
+	MC_RSP_OP(cmd, 1, 40,  8, enum dpmac_eth_if,	attr->eth_if);\
+	MC_RSP_OP(cmd, 2, 0,  32, uint32_t,		attr->max_rate);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_MDIO_READ(cmd, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  cfg->phy_addr); \
+	MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  cfg->reg); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_RSP_MDIO_READ(cmd, data) \
+	MC_RSP_OP(cmd, 0, 16, 16, uint16_t, data)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_MDIO_WRITE(cmd, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  cfg->phy_addr); \
+	MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  cfg->reg); \
+	MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->data); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_RSP_GET_LINK_CFG(cmd, cfg) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  64, uint64_t, cfg->options); \
+	MC_RSP_OP(cmd, 1, 0,  32, uint32_t, cfg->rate); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_SET_LINK_STATE(cmd, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  64, uint64_t, cfg->options); \
+	MC_CMD_OP(cmd, 1, 0,  32, uint32_t, cfg->rate); \
+	MC_CMD_OP(cmd, 2, 0,  1,  int,      cfg->up); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_CMD_GET_COUNTER(cmd, type) \
+	MC_CMD_OP(cmd, 0, 0,  8, enum dpmac_counter, type)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMAC_RSP_GET_COUNTER(cmd, counter) \
+	MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter)
+
+#endif /* _FSL_DPMAC_CMD_H */
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/mac/dpmac.c
@@ -0,0 +1,422 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "../../fsl-mc/include/mc-sys.h"
+#include "../../fsl-mc/include/mc-cmd.h"
+#include "dpmac.h"
+#include "dpmac-cmd.h"
+
+int dpmac_open(struct fsl_mc_io *mc_io,
+	       uint32_t cmd_flags,
+	       int dpmac_id,
+	       uint16_t *token)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN,
+					  cmd_flags,
+					  0);
+	DPMAC_CMD_OPEN(cmd, dpmac_id);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+	return err;
+}
+
+int dpmac_close(struct fsl_mc_io *mc_io,
+		uint32_t cmd_flags,
+		uint16_t token)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpmac_create(struct fsl_mc_io *mc_io,
+		 uint32_t cmd_flags,
+		 const struct dpmac_cfg *cfg,
+		 uint16_t *token)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE,
+					  cmd_flags,
+					  0);
+	DPMAC_CMD_CREATE(cmd, cfg);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+	return 0;
+}
+
+int dpmac_destroy(struct fsl_mc_io *mc_io,
+		  uint32_t cmd_flags,
+		  uint16_t token)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpmac_set_irq(struct fsl_mc_io	*mc_io,
+		  uint32_t		cmd_flags,
+		  uint16_t		token,
+		  uint8_t		irq_index,
+		  struct dpmac_irq_cfg	*irq_cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_SET_IRQ(cmd, irq_index, irq_cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpmac_get_irq(struct fsl_mc_io	*mc_io,
+		  uint32_t		cmd_flags,
+		  uint16_t		token,
+		  uint8_t		irq_index,
+		  int			*type,
+		  struct dpmac_irq_cfg	*irq_cfg)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_GET_IRQ(cmd, irq_index);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPMAC_RSP_GET_IRQ(cmd, *type, irq_cfg);
+
+	return 0;
+}
+
+int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token,
+			 uint8_t irq_index,
+			 uint8_t en)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_ENABLE,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token,
+			 uint8_t irq_index,
+			 uint8_t *en)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_ENABLE,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_GET_IRQ_ENABLE(cmd, irq_index);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPMAC_RSP_GET_IRQ_ENABLE(cmd, *en);
+
+	return 0;
+}
+
+int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
+		       uint32_t cmd_flags,
+		       uint16_t token,
+		       uint8_t irq_index,
+		       uint32_t mask)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_MASK,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_SET_IRQ_MASK(cmd, irq_index, mask);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
+		       uint32_t cmd_flags,
+		       uint16_t token,
+		       uint8_t irq_index,
+		       uint32_t *mask)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_MASK,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_GET_IRQ_MASK(cmd, irq_index);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPMAC_RSP_GET_IRQ_MASK(cmd, *mask);
+
+	return 0;
+}
+
+int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token,
+			 uint8_t irq_index,
+			 uint32_t *status)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_STATUS,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_GET_IRQ_STATUS(cmd, irq_index, *status);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPMAC_RSP_GET_IRQ_STATUS(cmd, *status);
+
+	return 0;
+}
+
+int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
+			   uint32_t cmd_flags,
+			   uint16_t token,
+			   uint8_t irq_index,
+			   uint32_t status)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLEAR_IRQ_STATUS,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpmac_get_attributes(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token,
+			 struct dpmac_attr *attr)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPMAC_RSP_GET_ATTRIBUTES(cmd, attr);
+
+	return 0;
+}
+
+int dpmac_mdio_read(struct fsl_mc_io *mc_io,
+		    uint32_t cmd_flags,
+		    uint16_t token,
+		    struct dpmac_mdio_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_READ,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_MDIO_READ(cmd, cfg);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPMAC_RSP_MDIO_READ(cmd, cfg->data);
+
+	return 0;
+}
+
+int dpmac_mdio_write(struct fsl_mc_io *mc_io,
+		     uint32_t cmd_flags,
+		     uint16_t token,
+		     struct dpmac_mdio_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_WRITE,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_MDIO_WRITE(cmd, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
+		       uint32_t cmd_flags,
+		       uint16_t token,
+		       struct dpmac_link_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+	int err = 0;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	DPMAC_RSP_GET_LINK_CFG(cmd, cfg);
+
+	return 0;
+}
+
+int dpmac_set_link_state(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token,
+			 struct dpmac_link_state *link_state)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_SET_LINK_STATE(cmd, link_state);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpmac_get_counter(struct fsl_mc_io *mc_io,
+		      uint32_t cmd_flags,
+		      uint16_t token,
+		      enum dpmac_counter type,
+		      uint64_t *counter)
+{
+	struct mc_command cmd = { 0 };
+	int err = 0;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER,
+					  cmd_flags,
+					  token);
+	DPMAC_CMD_GET_COUNTER(cmd, type);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	DPMAC_RSP_GET_COUNTER(cmd, *counter);
+
+	return 0;
+}
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/mac/dpmac.h
@@ -0,0 +1,593 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __FSL_DPMAC_H
+#define __FSL_DPMAC_H
+
+/* Data Path MAC API
+ * Contains initialization APIs and runtime control APIs for DPMAC
+ */
+
+struct fsl_mc_io;
+
+/**
+ * dpmac_open() - Open a control session for the specified object.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @dpmac_id:	DPMAC unique ID
+ * @token:	Returned token; use in subsequent API calls
+ *
+ * This function can be used to open a control session for an
+ * already created object; an object may have been declared in
+ * the DPL or by calling the dpmac_create function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent commands for
+ * this specific object
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_open(struct fsl_mc_io	*mc_io,
+	       uint32_t		cmd_flags,
+	       int			dpmac_id,
+	       uint16_t		*token);
+
+/**
+ * dpmac_close() - Close the control session of the object
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ *
+ * After this function is called, no further operations are
+ * allowed on the object without opening a new control session.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_close(struct fsl_mc_io	*mc_io,
+		uint32_t		cmd_flags,
+		uint16_t		token);
+
+/**
+ * enum dpmac_link_type -  DPMAC link type
+ * @DPMAC_LINK_TYPE_NONE: No link
+ * @DPMAC_LINK_TYPE_FIXED: Link is fixed type
+ * @DPMAC_LINK_TYPE_PHY: Link by PHY ID
+ * @DPMAC_LINK_TYPE_BACKPLANE: Backplane link type
+ */
+enum dpmac_link_type {
+	DPMAC_LINK_TYPE_NONE,
+	DPMAC_LINK_TYPE_FIXED,
+	DPMAC_LINK_TYPE_PHY,
+	DPMAC_LINK_TYPE_BACKPLANE
+};
+
+/**
+ * enum dpmac_eth_if - DPMAC Ethrnet interface
+ * @DPMAC_ETH_IF_MII: MII interface
+ * @DPMAC_ETH_IF_RMII: RMII interface
+ * @DPMAC_ETH_IF_SMII: SMII interface
+ * @DPMAC_ETH_IF_GMII: GMII interface
+ * @DPMAC_ETH_IF_RGMII: RGMII interface
+ * @DPMAC_ETH_IF_SGMII: SGMII interface
+ * @DPMAC_ETH_IF_QSGMII: QSGMII interface
+ * @DPMAC_ETH_IF_XAUI: XAUI interface
+ * @DPMAC_ETH_IF_XFI: XFI interface
+ */
+enum dpmac_eth_if {
+	DPMAC_ETH_IF_MII,
+	DPMAC_ETH_IF_RMII,
+	DPMAC_ETH_IF_SMII,
+	DPMAC_ETH_IF_GMII,
+	DPMAC_ETH_IF_RGMII,
+	DPMAC_ETH_IF_SGMII,
+	DPMAC_ETH_IF_QSGMII,
+	DPMAC_ETH_IF_XAUI,
+	DPMAC_ETH_IF_XFI
+};
+
+/**
+ * struct dpmac_cfg - Structure representing DPMAC configuration
+ * @mac_id:	Represents the Hardware MAC ID; in case of multiple WRIOP,
+ *		the MAC IDs are continuous.
+ *		For example:  2 WRIOPs, 16 MACs in each:
+ *				MAC IDs for the 1st WRIOP: 1-16,
+ *				MAC IDs for the 2nd WRIOP: 17-32.
+ */
+struct dpmac_cfg {
+	int mac_id;
+};
+
+/**
+ * dpmac_create() - Create the DPMAC object.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @cfg:	Configuration structure
+ * @token:	Returned token; use in subsequent API calls
+ *
+ * Create the DPMAC object, allocate required resources and
+ * perform required initialization.
+ *
+ * The object can be created either by declaring it in the
+ * DPL file, or by calling this function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent calls to
+ * this specific object. For objects that are created using the
+ * DPL file, call dpmac_open function to get an authentication
+ * token first.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_create(struct fsl_mc_io	*mc_io,
+		 uint32_t		cmd_flags,
+		 const struct dpmac_cfg	*cfg,
+		 uint16_t		*token);
+
+/**
+ * dpmac_destroy() - Destroy the DPMAC object and release all its resources.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpmac_destroy(struct fsl_mc_io	*mc_io,
+		  uint32_t		cmd_flags,
+		  uint16_t		token);
+
+/**
+ * DPMAC IRQ Index and Events
+ */
+
+/**
+ * IRQ index
+ */
+#define DPMAC_IRQ_INDEX						0
+/**
+ * IRQ event - indicates a change in link state
+ */
+#define DPMAC_IRQ_EVENT_LINK_CFG_REQ		0x00000001
+/**
+ * IRQ event - Indicates that the link state changed
+ */
+#define DPMAC_IRQ_EVENT_LINK_CHANGED		0x00000002
+
+/**
+ * struct dpmac_irq_cfg - IRQ configuration
+ * @addr:	Address that must be written to signal a message-based interrupt
+ * @val:	Value to write into irq_addr address
+ * @irq_num: A user defined number associated with this IRQ
+ */
+struct dpmac_irq_cfg {
+	     uint64_t		addr;
+	     uint32_t		val;
+	     int		irq_num;
+};
+
+/**
+ * dpmac_set_irq() - Set IRQ information for the DPMAC to trigger an interrupt.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @irq_index:	Identifies the interrupt index to configure
+ * @irq_cfg:	IRQ configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_set_irq(struct fsl_mc_io	*mc_io,
+		  uint32_t		cmd_flags,
+		  uint16_t		token,
+		  uint8_t		irq_index,
+		  struct dpmac_irq_cfg	*irq_cfg);
+
+/**
+ * dpmac_get_irq() - Get IRQ information from the DPMAC.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @irq_index:	The interrupt index to configure
+ * @type:	Interrupt type: 0 represents message interrupt
+ *		type (both irq_addr and irq_val are valid)
+ * @irq_cfg:	IRQ attributes
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_get_irq(struct fsl_mc_io	*mc_io,
+		  uint32_t		cmd_flags,
+		  uint16_t		token,
+		  uint8_t		irq_index,
+		  int			*type,
+		  struct dpmac_irq_cfg	*irq_cfg);
+
+/**
+ * dpmac_set_irq_enable() - Set overall interrupt state.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @irq_index:	The interrupt index to configure
+ * @en:	Interrupt state - enable = 1, disable = 0
+ *
+ * Allows GPP software to control when interrupts are generated.
+ * Each interrupt can have up to 32 causes.  The enable/disable control's the
+ * overall interrupt state. if the interrupt is disabled no causes will cause
+ * an interrupt.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_set_irq_enable(struct fsl_mc_io	*mc_io,
+			 uint32_t		cmd_flags,
+			 uint16_t		token,
+			 uint8_t		irq_index,
+			 uint8_t		en);
+
+/**
+ * dpmac_get_irq_enable() - Get overall interrupt state
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @irq_index:	The interrupt index to configure
+ * @en:		Returned interrupt state - enable = 1, disable = 0
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_get_irq_enable(struct fsl_mc_io	*mc_io,
+			 uint32_t		cmd_flags,
+			 uint16_t		token,
+			 uint8_t		irq_index,
+			 uint8_t		*en);
+
+/**
+ * dpmac_set_irq_mask() - Set interrupt mask.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @irq_index:	The interrupt index to configure
+ * @mask:	Event mask to trigger interrupt;
+ *			each bit:
+ *				0 = ignore event
+ *				1 = consider event for asserting IRQ
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
+		       uint32_t	cmd_flags,
+		       uint16_t		token,
+		       uint8_t		irq_index,
+		       uint32_t		mask);
+
+/**
+ * dpmac_get_irq_mask() - Get interrupt mask.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @irq_index:	The interrupt index to configure
+ * @mask:	Returned event mask to trigger interrupt
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
+		       uint32_t	cmd_flags,
+		       uint16_t		token,
+		       uint8_t		irq_index,
+		       uint32_t		*mask);
+
+/**
+ * dpmac_get_irq_status() - Get the current status of any pending interrupts.
+ *
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @irq_index:	The interrupt index to configure
+ * @status:	Returned interrupts status - one bit per cause:
+ *			0 = no interrupt pending
+ *			1 = interrupt pending
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_get_irq_status(struct fsl_mc_io	*mc_io,
+			 uint32_t		cmd_flags,
+			 uint16_t		token,
+			 uint8_t		irq_index,
+			 uint32_t		*status);
+
+/**
+ * dpmac_clear_irq_status() - Clear a pending interrupt's status
+ *
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @irq_index:	The interrupt index to configure
+ * @status:	Bits to clear (W1C) - one bit per cause:
+ *					0 = don't change
+ *					1 = clear status bit
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_clear_irq_status(struct fsl_mc_io	*mc_io,
+			   uint32_t		cmd_flags,
+			   uint16_t		token,
+			   uint8_t		irq_index,
+			   uint32_t		status);
+
+/**
+ * struct dpmac_attr - Structure representing DPMAC attributes
+ * @id:		DPMAC object ID
+ * @phy_id:	PHY ID
+ * @link_type: link type
+ * @eth_if: Ethernet interface
+ * @max_rate: Maximum supported rate - in Mbps
+ * @version:	DPMAC version
+ */
+struct dpmac_attr {
+	int			id;
+	int			phy_id;
+	enum dpmac_link_type	link_type;
+	enum dpmac_eth_if	eth_if;
+	uint32_t		max_rate;
+	/**
+	 * struct version - Structure representing DPMAC version
+	 * @major:	DPMAC major version
+	 * @minor:	DPMAC minor version
+	 */
+	struct {
+		uint16_t major;
+		uint16_t minor;
+	} version;
+};
+
+/**
+ * dpmac_get_attributes - Retrieve DPMAC attributes.
+ *
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @attr:	Returned object's attributes
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_get_attributes(struct fsl_mc_io	*mc_io,
+			 uint32_t		cmd_flags,
+			 uint16_t		token,
+			 struct dpmac_attr	*attr);
+
+/**
+ * struct dpmac_mdio_cfg - DPMAC MDIO read/write parameters
+ * @phy_addr: MDIO device address
+ * @reg: Address of the register within the Clause 45 PHY device from which data
+ *	is to be read
+ * @data: Data read/write from/to MDIO
+ */
+struct dpmac_mdio_cfg {
+	uint8_t		phy_addr;
+	uint8_t		reg;
+	uint16_t	data;
+};
+
+/**
+ * dpmac_mdio_read() - Perform MDIO read transaction
+ * @mc_io:	Pointer to opaque I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @cfg:	Structure with MDIO transaction parameters
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_mdio_read(struct fsl_mc_io		*mc_io,
+		    uint32_t			cmd_flags,
+		    uint16_t			token,
+		    struct dpmac_mdio_cfg	*cfg);
+
+/**
+ * dpmac_mdio_write() - Perform MDIO write transaction
+ * @mc_io:	Pointer to opaque I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @cfg:	Structure with MDIO transaction parameters
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_mdio_write(struct fsl_mc_io		*mc_io,
+		     uint32_t			cmd_flags,
+		     uint16_t			token,
+		     struct dpmac_mdio_cfg	*cfg);
+
+/**
+ * DPMAC link configuration/state options
+ */
+
+/**
+ * Enable auto-negotiation
+ */
+#define DPMAC_LINK_OPT_AUTONEG		0x0000000000000001ULL
+/**
+ * Enable half-duplex mode
+ */
+#define DPMAC_LINK_OPT_HALF_DUPLEX	0x0000000000000002ULL
+/**
+ * Enable pause frames
+ */
+#define DPMAC_LINK_OPT_PAUSE		0x0000000000000004ULL
+/**
+ * Enable a-symmetric pause frames
+ */
+#define DPMAC_LINK_OPT_ASYM_PAUSE	0x0000000000000008ULL
+
+/**
+ * struct dpmac_link_cfg - Structure representing DPMAC link configuration
+ * @rate: Link's rate - in Mbps
+ * @options: Enable/Disable DPMAC link cfg features (bitmap)
+ */
+struct dpmac_link_cfg {
+	uint32_t rate;
+	uint64_t options;
+};
+
+/**
+ * dpmac_get_link_cfg() - Get Ethernet link configuration
+ * @mc_io:	Pointer to opaque I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @cfg:	Returned structure with the link configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_get_link_cfg(struct fsl_mc_io	*mc_io,
+		       uint32_t		cmd_flags,
+		       uint16_t		token,
+		       struct dpmac_link_cfg	*cfg);
+
+/**
+ * struct dpmac_link_state - DPMAC link configuration request
+ * @rate: Rate in Mbps
+ * @options: Enable/Disable DPMAC link cfg features (bitmap)
+ * @up: Link state
+ */
+struct dpmac_link_state {
+	uint32_t	rate;
+	uint64_t	options;
+	int		up;
+};
+
+/**
+ * dpmac_set_link_state() - Set the Ethernet link status
+ * @mc_io:	Pointer to opaque I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @link_state:	Link state configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpmac_set_link_state(struct fsl_mc_io		*mc_io,
+			 uint32_t			cmd_flags,
+			 uint16_t			token,
+			 struct dpmac_link_state	*link_state);
+
+/**
+ * enum dpmac_counter - DPMAC counter types
+ * @DPMAC_CNT_ING_FRAME_64: counts 64-bytes frames, good or bad.
+ * @DPMAC_CNT_ING_FRAME_127: counts 65- to 127-bytes frames, good or bad.
+ * @DPMAC_CNT_ING_FRAME_255: counts 128- to 255-bytes frames, good or bad.
+ * @DPMAC_CNT_ING_FRAME_511: counts 256- to 511-bytes frames, good or bad.
+ * @DPMAC_CNT_ING_FRAME_1023: counts 512- to 1023-bytes frames, good or bad.
+ * @DPMAC_CNT_ING_FRAME_1518: counts 1024- to 1518-bytes frames, good or bad.
+ * @DPMAC_CNT_ING_FRAME_1519_MAX: counts 1519-bytes frames and larger
+ *				  (up to max frame length specified),
+ *				  good or bad.
+ * @DPMAC_CNT_ING_FRAG: counts frames which are shorter than 64 bytes received
+ *			with a wrong CRC
+ * @DPMAC_CNT_ING_JABBER: counts frames longer than the maximum frame length
+ *			  specified, with a bad frame check sequence.
+ * @DPMAC_CNT_ING_FRAME_DISCARD: counts dropped frames due to internal errors.
+ *				 Occurs when a receive FIFO overflows.
+ *				 Includes also frames truncated as a result of
+ *				 the receive FIFO overflow.
+ * @DPMAC_CNT_ING_ALIGN_ERR: counts frames with an alignment error
+ *			     (optional used for wrong SFD).
+ * @DPMAC_CNT_EGR_UNDERSIZED: counts frames transmitted that was less than 64
+ *			      bytes long with a good CRC.
+ * @DPMAC_CNT_ING_OVERSIZED: counts frames longer than the maximum frame length
+ *			     specified, with a good frame check sequence.
+ * @DPMAC_CNT_ING_VALID_PAUSE_FRAME: counts valid pause frames (regular and PFC)
+ * @DPMAC_CNT_EGR_VALID_PAUSE_FRAME: counts valid pause frames transmitted
+ *				     (regular and PFC).
+ * @DPMAC_CNT_ING_BYTE: counts bytes received except preamble for all valid
+ *			frames and valid pause frames.
+ * @DPMAC_CNT_ING_MCAST_FRAME: counts received multicast frames.
+ * @DPMAC_CNT_ING_BCAST_FRAME: counts received broadcast frames.
+ * @DPMAC_CNT_ING_ALL_FRAME: counts each good or bad frames received.
+ * @DPMAC_CNT_ING_UCAST_FRAME: counts received unicast frames.
+ * @DPMAC_CNT_ING_ERR_FRAME: counts frames received with an error
+ *			     (except for undersized/fragment frame).
+ * @DPMAC_CNT_EGR_BYTE: counts bytes transmitted except preamble for all valid
+ *			frames and valid pause frames transmitted.
+ * @DPMAC_CNT_EGR_MCAST_FRAME: counts transmitted multicast frames.
+ * @DPMAC_CNT_EGR_BCAST_FRAME: counts transmitted broadcast frames.
+ * @DPMAC_CNT_EGR_UCAST_FRAME: counts transmitted unicast frames.
+ * @DPMAC_CNT_EGR_ERR_FRAME: counts frames transmitted with an error.
+ * @DPMAC_CNT_ING_GOOD_FRAME: counts frames received without error, including
+ *			      pause frames.
+ * @DPMAC_CNT_ENG_GOOD_FRAME: counts frames transmitted without error, including
+ *			      pause frames.
+ */
+enum dpmac_counter {
+	DPMAC_CNT_ING_FRAME_64,
+	DPMAC_CNT_ING_FRAME_127,
+	DPMAC_CNT_ING_FRAME_255,
+	DPMAC_CNT_ING_FRAME_511,
+	DPMAC_CNT_ING_FRAME_1023,
+	DPMAC_CNT_ING_FRAME_1518,
+	DPMAC_CNT_ING_FRAME_1519_MAX,
+	DPMAC_CNT_ING_FRAG,
+	DPMAC_CNT_ING_JABBER,
+	DPMAC_CNT_ING_FRAME_DISCARD,
+	DPMAC_CNT_ING_ALIGN_ERR,
+	DPMAC_CNT_EGR_UNDERSIZED,
+	DPMAC_CNT_ING_OVERSIZED,
+	DPMAC_CNT_ING_VALID_PAUSE_FRAME,
+	DPMAC_CNT_EGR_VALID_PAUSE_FRAME,
+	DPMAC_CNT_ING_BYTE,
+	DPMAC_CNT_ING_MCAST_FRAME,
+	DPMAC_CNT_ING_BCAST_FRAME,
+	DPMAC_CNT_ING_ALL_FRAME,
+	DPMAC_CNT_ING_UCAST_FRAME,
+	DPMAC_CNT_ING_ERR_FRAME,
+	DPMAC_CNT_EGR_BYTE,
+	DPMAC_CNT_EGR_MCAST_FRAME,
+	DPMAC_CNT_EGR_BCAST_FRAME,
+	DPMAC_CNT_EGR_UCAST_FRAME,
+	DPMAC_CNT_EGR_ERR_FRAME,
+	DPMAC_CNT_ING_GOOD_FRAME,
+	DPMAC_CNT_ENG_GOOD_FRAME
+};
+
+/**
+ * dpmac_get_counter() - Read a specific DPMAC counter
+ * @mc_io:	Pointer to opaque I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPMAC object
+ * @type:	The requested counter
+ * @counter:	Returned counter value
+ *
+ * Return:	The requested counter; '0' otherwise.
+ */
+int dpmac_get_counter(struct fsl_mc_io		*mc_io,
+		      uint32_t			cmd_flags,
+		      uint16_t			token,
+		      enum dpmac_counter	 type,
+		      uint64_t			*counter);
+
+#endif /* __FSL_DPMAC_H */
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/mac/mac.c
@@ -0,0 +1,767 @@
+/* Copyright 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
+
+#include <uapi/linux/if_bridge.h>
+#include <net/netlink.h>
+
+#include <linux/of.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
+#include <linux/interrupt.h>
+#include <linux/msi.h>
+
+#include "../../fsl-mc/include/mc.h"
+#include "../../fsl-mc/include/mc-sys.h"
+
+#include "dpmac.h"
+#include "dpmac-cmd.h"
+
+#define DPAA2_SUPPORTED_DPMAC_VERSION	3
+
+struct dpaa2_mac_priv {
+	struct net_device		*netdev;
+	struct fsl_mc_device		*mc_dev;
+	struct dpmac_attr		attr;
+	struct dpmac_link_state		old_state;
+};
+
+/* TODO: fix the 10G modes, mapping can't be right:
+ *  XGMII is paralel
+ *  XAUI is serial, using 8b/10b encoding
+ *  XFI is also serial but using 64b/66b encoding
+ * they can't all map to XGMII...
+ *
+ * This must be kept in sync with enum dpmac_eth_if.
+ */
+static phy_interface_t dpaa2_mac_iface_mode[] =  {
+	/* DPMAC_ETH_IF_MII */
+	PHY_INTERFACE_MODE_MII,
+	/* DPMAC_ETH_IF_RMII */
+	PHY_INTERFACE_MODE_RMII,
+	/* DPMAC_ETH_IF_SMII */
+	PHY_INTERFACE_MODE_SMII,
+	/* DPMAC_ETH_IF_GMII */
+	PHY_INTERFACE_MODE_GMII,
+	/* DPMAC_ETH_IF_RGMII */
+	PHY_INTERFACE_MODE_RGMII,
+	/* DPMAC_ETH_IF_SGMII */
+	PHY_INTERFACE_MODE_SGMII,
+	/* DPMAC_ETH_IF_QSGMII */
+	PHY_INTERFACE_MODE_QSGMII,
+	/* DPMAC_ETH_IF_XAUI */
+	PHY_INTERFACE_MODE_XGMII,
+	/* DPMAC_ETH_IF_XFI */
+	PHY_INTERFACE_MODE_XGMII,
+};
+
+static void dpaa2_mac_link_changed(struct net_device *netdev)
+{
+	struct phy_device	*phydev;
+	struct dpmac_link_state	state = { 0 };
+	struct dpaa2_mac_priv	*priv = netdev_priv(netdev);
+	int			err;
+
+	/* the PHY just notified us of link state change */
+	phydev = netdev->phydev;
+
+	state.up = !!phydev->link;
+	if (phydev->link) {
+		state.rate = phydev->speed;
+
+		if (!phydev->duplex)
+			state.options |= DPMAC_LINK_OPT_HALF_DUPLEX;
+		if (phydev->autoneg)
+			state.options |= DPMAC_LINK_OPT_AUTONEG;
+
+		netif_carrier_on(netdev);
+	} else {
+		netif_carrier_off(netdev);
+	}
+
+	if (priv->old_state.up != state.up ||
+	    priv->old_state.rate != state.rate ||
+	    priv->old_state.options != state.options) {
+		priv->old_state = state;
+		phy_print_status(phydev);
+	}
+
+	/* We must call into the MC firmware at all times, because we don't know
+	 * when and whether a potential DPNI may have read the link state.
+	 */
+	err = dpmac_set_link_state(priv->mc_dev->mc_io, 0,
+				   priv->mc_dev->mc_handle, &state);
+	if (unlikely(err))
+		dev_err(&priv->mc_dev->dev, "dpmac_set_link_state: %d\n", err);
+}
+
+/* IRQ bits that we handle */
+static const u32 dpmac_irq_mask =  DPMAC_IRQ_EVENT_LINK_CFG_REQ;
+
+#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
+static netdev_tx_t dpaa2_mac_drop_frame(struct sk_buff *skb,
+					struct net_device *dev)
+{
+	/* we don't support I/O for now, drop the frame */
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+static int dpaa2_mac_open(struct net_device *netdev)
+{
+	/* start PHY state machine */
+	phy_start(netdev->phydev);
+
+	return 0;
+}
+
+static int dpaa2_mac_stop(struct net_device *netdev)
+{
+	if (!netdev->phydev)
+		goto done;
+
+	/* stop PHY state machine */
+	phy_stop(netdev->phydev);
+
+	/* signal link down to firmware */
+	netdev->phydev->link = 0;
+	dpaa2_mac_link_changed(netdev);
+
+done:
+	return 0;
+}
+
+static int dpaa2_mac_get_settings(struct net_device *netdev,
+				  struct ethtool_cmd *cmd)
+{
+	return phy_ethtool_gset(netdev->phydev, cmd);
+}
+
+static int dpaa2_mac_set_settings(struct net_device *netdev,
+				  struct ethtool_cmd *cmd)
+{
+	return phy_ethtool_sset(netdev->phydev, cmd);
+}
+
+static struct rtnl_link_stats64
+*dpaa2_mac_get_stats(struct net_device *netdev,
+		     struct rtnl_link_stats64 *storage)
+{
+	struct dpaa2_mac_priv	*priv = netdev_priv(netdev);
+	u64			tmp;
+	int			err;
+
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_EGR_MCAST_FRAME,
+				&storage->tx_packets);
+	if (err)
+		goto error;
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_EGR_BCAST_FRAME, &tmp);
+	if (err)
+		goto error;
+	storage->tx_packets += tmp;
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_EGR_UCAST_FRAME, &tmp);
+	if (err)
+		goto error;
+	storage->tx_packets += tmp;
+
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_EGR_UNDERSIZED, &storage->tx_dropped);
+	if (err)
+		goto error;
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_EGR_BYTE, &storage->tx_bytes);
+	if (err)
+		goto error;
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_EGR_ERR_FRAME, &storage->tx_errors);
+	if (err)
+		goto error;
+
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_ING_ALL_FRAME, &storage->rx_packets);
+	if (err)
+		goto error;
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_ING_MCAST_FRAME, &storage->multicast);
+	if (err)
+		goto error;
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_ING_FRAME_DISCARD,
+				&storage->rx_dropped);
+	if (err)
+		goto error;
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_ING_ALIGN_ERR, &storage->rx_errors);
+	if (err)
+		goto error;
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_ING_OVERSIZED, &tmp);
+	if (err)
+		goto error;
+	storage->rx_errors += tmp;
+	err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
+				DPMAC_CNT_ING_BYTE, &storage->rx_bytes);
+	if (err)
+		goto error;
+
+	return storage;
+
+error:
+	netdev_err(netdev, "dpmac_get_counter err %d\n", err);
+	return storage;
+}
+
+static struct {
+	enum dpmac_counter id;
+	char name[ETH_GSTRING_LEN];
+} dpaa2_mac_counters[] =  {
+	{DPMAC_CNT_ING_ALL_FRAME,		"rx all frames"},
+	{DPMAC_CNT_ING_GOOD_FRAME,		"rx frames ok"},
+	{DPMAC_CNT_ING_ERR_FRAME,		"rx frame errors"},
+	{DPMAC_CNT_ING_FRAME_DISCARD,		"rx frame discards"},
+	{DPMAC_CNT_ING_UCAST_FRAME,		"rx u-cast"},
+	{DPMAC_CNT_ING_BCAST_FRAME,		"rx b-cast"},
+	{DPMAC_CNT_ING_MCAST_FRAME,		"rx m-cast"},
+	{DPMAC_CNT_ING_FRAME_64,		"rx 64 bytes"},
+	{DPMAC_CNT_ING_FRAME_127,		"rx 65-127 bytes"},
+	{DPMAC_CNT_ING_FRAME_255,		"rx 128-255 bytes"},
+	{DPMAC_CNT_ING_FRAME_511,		"rx 256-511 bytes"},
+	{DPMAC_CNT_ING_FRAME_1023,		"rx 512-1023 bytes"},
+	{DPMAC_CNT_ING_FRAME_1518,		"rx 1024-1518 bytes"},
+	{DPMAC_CNT_ING_FRAME_1519_MAX,		"rx 1519-max bytes"},
+	{DPMAC_CNT_ING_FRAG,			"rx frags"},
+	{DPMAC_CNT_ING_JABBER,			"rx jabber"},
+	{DPMAC_CNT_ING_ALIGN_ERR,		"rx align errors"},
+	{DPMAC_CNT_ING_OVERSIZED,		"rx oversized"},
+	{DPMAC_CNT_ING_VALID_PAUSE_FRAME,	"rx pause"},
+	{DPMAC_CNT_ING_BYTE,			"rx bytes"},
+	{DPMAC_CNT_ENG_GOOD_FRAME,		"tx frames ok"},
+	{DPMAC_CNT_EGR_UCAST_FRAME,		"tx u-cast"},
+	{DPMAC_CNT_EGR_MCAST_FRAME,		"tx m-cast"},
+	{DPMAC_CNT_EGR_BCAST_FRAME,		"tx b-cast"},
+	{DPMAC_CNT_EGR_ERR_FRAME,		"tx frame errors"},
+	{DPMAC_CNT_EGR_UNDERSIZED,		"tx undersized"},
+	{DPMAC_CNT_EGR_VALID_PAUSE_FRAME,	"tx b-pause"},
+	{DPMAC_CNT_EGR_BYTE,			"tx bytes"},
+
+};
+
+static void dpaa2_mac_get_strings(struct net_device *netdev,
+				  u32 stringset, u8 *data)
+{
+	int i;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++)
+			memcpy(data + i * ETH_GSTRING_LEN,
+			       dpaa2_mac_counters[i].name,
+			       ETH_GSTRING_LEN);
+		break;
+	}
+}
+
+static void dpaa2_mac_get_ethtool_stats(struct net_device *netdev,
+					struct ethtool_stats *stats,
+					u64 *data)
+{
+	struct dpaa2_mac_priv	*priv = netdev_priv(netdev);
+	int			i;
+	int			err;
+
+	for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++) {
+		err = dpmac_get_counter(priv->mc_dev->mc_io,
+					0,
+					priv->mc_dev->mc_handle,
+					dpaa2_mac_counters[i].id, &data[i]);
+		if (err)
+			netdev_err(netdev, "dpmac_get_counter[%s] err %d\n",
+				   dpaa2_mac_counters[i].name, err);
+	}
+}
+
+static int dpaa2_mac_get_sset_count(struct net_device *dev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return ARRAY_SIZE(dpaa2_mac_counters);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static const struct net_device_ops dpaa2_mac_ndo_ops = {
+	.ndo_start_xmit		= &dpaa2_mac_drop_frame,
+	.ndo_open		= &dpaa2_mac_open,
+	.ndo_stop		= &dpaa2_mac_stop,
+	.ndo_get_stats64	= &dpaa2_mac_get_stats,
+};
+
+static const struct ethtool_ops dpaa2_mac_ethtool_ops = {
+	.get_settings		= &dpaa2_mac_get_settings,
+	.set_settings		= &dpaa2_mac_set_settings,
+	.get_strings		= &dpaa2_mac_get_strings,
+	.get_ethtool_stats	= &dpaa2_mac_get_ethtool_stats,
+	.get_sset_count		= &dpaa2_mac_get_sset_count,
+};
+#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
+
+static int configure_link(struct dpaa2_mac_priv *priv,
+			  struct dpmac_link_cfg *cfg)
+{
+	struct phy_device *phydev = priv->netdev->phydev;
+
+	if (!phydev) {
+		dev_warn(priv->netdev->dev.parent,
+			 "asked to change PHY settings but PHY ref is NULL, ignoring\n");
+		return 0;
+	}
+
+	phydev->speed = cfg->rate;
+	phydev->duplex  = !!(cfg->options & DPMAC_LINK_OPT_HALF_DUPLEX);
+
+	if (cfg->options & DPMAC_LINK_OPT_AUTONEG) {
+		phydev->autoneg = 1;
+		phydev->advertising |= ADVERTISED_Autoneg;
+	} else {
+		phydev->autoneg = 0;
+		phydev->advertising &= ~ADVERTISED_Autoneg;
+	}
+
+	phy_start_aneg(phydev);
+
+	return 0;
+}
+
+static irqreturn_t dpaa2_mac_irq_handler(int irq_num, void *arg)
+{
+	struct device *dev = (struct device *)arg;
+	struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+	struct dpaa2_mac_priv *priv = dev_get_drvdata(dev);
+	struct dpmac_link_cfg link_cfg;
+	u8 irq_index = DPMAC_IRQ_INDEX;
+	u32 status, clear = 0;
+	int err;
+
+	if (mc_dev->irqs[0]->msi_desc->irq != irq_num) {
+		dev_err(dev, "received unexpected interrupt %d!\n", irq_num);
+		goto err;
+	}
+
+	err = dpmac_get_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
+				   irq_index, &status);
+	if (err) {
+		dev_err(dev, "dpmac_get_irq_status err %d\n", err);
+		clear = ~0x0u;
+		goto out;
+	}
+
+	/* DPNI-initiated link configuration; 'ifconfig up' also calls this */
+	if (status & DPMAC_IRQ_EVENT_LINK_CFG_REQ) {
+		dev_dbg(dev, "DPMAC IRQ %d - LINK_CFG_REQ\n", irq_num);
+		clear |= DPMAC_IRQ_EVENT_LINK_CFG_REQ;
+
+		err = dpmac_get_link_cfg(mc_dev->mc_io, 0, mc_dev->mc_handle,
+					 &link_cfg);
+		if (err) {
+			dev_err(dev, "dpmac_get_link_cfg err %d\n", err);
+			goto out;
+		}
+
+		err = configure_link(priv, &link_cfg);
+		if (err) {
+			dev_err(dev, "cannot configure link\n");
+			goto out;
+		}
+	}
+
+out:
+	err = dpmac_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
+				     irq_index, clear);
+	if (err < 0)
+		dev_err(&mc_dev->dev, "dpmac_clear_irq_status() err %d\n", err);
+
+	return IRQ_HANDLED;
+
+err:
+	dev_warn(dev, "DPMAC IRQ %d was not handled!\n", irq_num);
+	return IRQ_NONE;
+}
+
+static int setup_irqs(struct fsl_mc_device *mc_dev)
+{
+	int err;
+
+	err = fsl_mc_allocate_irqs(mc_dev);
+	if (err) {
+		dev_err(&mc_dev->dev, "fsl_mc_allocate_irqs err %d\n", err);
+		return err;
+	}
+
+	err = dpmac_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
+				 DPMAC_IRQ_INDEX, dpmac_irq_mask);
+	if (err < 0) {
+		dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err);
+		goto free_irq;
+	}
+	err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
+				   DPMAC_IRQ_INDEX, 0);
+	if (err) {
+		dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
+		goto free_irq;
+	}
+
+	err = devm_request_threaded_irq(&mc_dev->dev,
+					mc_dev->irqs[0]->msi_desc->irq,
+					NULL, &dpaa2_mac_irq_handler,
+					IRQF_NO_SUSPEND | IRQF_ONESHOT,
+					dev_name(&mc_dev->dev), &mc_dev->dev);
+	if (err) {
+		dev_err(&mc_dev->dev, "devm_request_threaded_irq err %d\n",
+			err);
+		goto free_irq;
+	}
+
+	err = dpmac_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
+				 DPMAC_IRQ_INDEX, dpmac_irq_mask);
+	if (err < 0) {
+		dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err);
+		goto free_irq;
+	}
+	err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
+				   DPMAC_IRQ_INDEX, 1);
+	if (err) {
+		dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
+		goto unregister_irq;
+	}
+
+	return 0;
+
+unregister_irq:
+	devm_free_irq(&mc_dev->dev, mc_dev->irqs[0]->msi_desc->irq, &mc_dev->dev);
+free_irq:
+	fsl_mc_free_irqs(mc_dev);
+
+	return err;
+}
+
+static void teardown_irqs(struct fsl_mc_device *mc_dev)
+{
+	int err;
+
+	err = dpmac_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
+				 DPMAC_IRQ_INDEX, dpmac_irq_mask);
+	if (err < 0)
+		dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err);
+
+	err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
+				   DPMAC_IRQ_INDEX, 0);
+	if (err < 0)
+		dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
+
+	devm_free_irq(&mc_dev->dev, mc_dev->irqs[0]->msi_desc->irq, &mc_dev->dev);
+	fsl_mc_free_irqs(mc_dev);
+}
+
+static struct device_node *lookup_node(struct device *dev, int dpmac_id)
+{
+	struct device_node *dpmacs, *dpmac = NULL;
+	struct device_node *mc_node = dev->of_node;
+	const void *id;
+	int lenp;
+	int dpmac_id_be32 = cpu_to_be32(dpmac_id);
+
+	dpmacs = of_find_node_by_name(mc_node, "dpmacs");
+	if (!dpmacs) {
+		dev_err(dev, "No dpmacs subnode in device-tree\n");
+		return NULL;
+	}
+
+	while ((dpmac = of_get_next_child(dpmacs, dpmac))) {
+		id = of_get_property(dpmac, "reg", &lenp);
+		if (!id || lenp != sizeof(int)) {
+			dev_warn(dev, "Unsuitable reg property in dpmac node\n");
+			continue;
+		}
+		if (*(int *)id == dpmac_id_be32)
+			return dpmac;
+	}
+
+	return NULL;
+}
+
+static int check_dpmac_version(struct dpaa2_mac_priv *priv)
+{
+	struct device *dev = &priv->mc_dev->dev;
+	int mc_version = priv->attr.version.major;
+
+	/* Check that the FLIB-defined version matches the one reported by MC */
+	if (mc_version != DPMAC_VER_MAJOR) {
+		dev_err(dev, "DPMAC FLIB version mismatch: MC says %d, we have %d\n",
+			mc_version, DPMAC_VER_MAJOR);
+		return -EINVAL;
+	}
+
+	/* ... and that we actually support it */
+	if (mc_version < DPAA2_SUPPORTED_DPMAC_VERSION) {
+		dev_err(dev, "Unsupported DPMAC FLIB version (%d)\n",
+			mc_version);
+		return -EINVAL;
+	}
+
+	dev_dbg(dev, "Using DPMAC FLIB version %d\n", mc_version);
+
+	return 0;
+}
+
+static int dpaa2_mac_probe(struct fsl_mc_device *mc_dev)
+{
+	struct device		*dev;
+	struct dpaa2_mac_priv	*priv = NULL;
+	struct device_node	*phy_node, *dpmac_node;
+	struct net_device	*netdev;
+	phy_interface_t		if_mode;
+	int			err = 0;
+
+	/* just being completely paranoid */
+	if (!mc_dev)
+		return -EFAULT;
+	dev = &mc_dev->dev;
+
+	/* prepare a net_dev structure to make the phy lib API happy */
+	netdev = alloc_etherdev(sizeof(*priv));
+	if (!netdev) {
+		dev_err(dev, "alloc_etherdev error\n");
+		err = -ENOMEM;
+		goto err_exit;
+	}
+	priv = netdev_priv(netdev);
+	priv->mc_dev = mc_dev;
+	priv->netdev = netdev;
+
+	SET_NETDEV_DEV(netdev, dev);
+	snprintf(netdev->name, IFNAMSIZ, "mac%d", mc_dev->obj_desc.id);
+
+	dev_set_drvdata(dev, priv);
+
+	err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io);
+	if (err || !mc_dev->mc_io) {
+		dev_err(dev, "fsl_mc_portal_allocate error: %d\n", err);
+		err = -ENODEV;
+		goto err_free_netdev;
+	}
+
+	err = dpmac_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
+			 &mc_dev->mc_handle);
+	if (err || !mc_dev->mc_handle) {
+		dev_err(dev, "dpmac_open error: %d\n", err);
+		err = -ENODEV;
+		goto err_free_mcp;
+	}
+
+	err = dpmac_get_attributes(mc_dev->mc_io, 0,
+				   mc_dev->mc_handle, &priv->attr);
+	if (err) {
+		dev_err(dev, "dpmac_get_attributes err %d\n", err);
+		err = -EINVAL;
+		goto err_close;
+	}
+
+	err = check_dpmac_version(priv);
+	if (err)
+		goto err_close;
+
+	/* Look up the DPMAC node in the device-tree. */
+	dpmac_node = lookup_node(dev, priv->attr.id);
+	if (!dpmac_node) {
+		dev_err(dev, "No dpmac@%d subnode found.\n", priv->attr.id);
+		err = -ENODEV;
+		goto err_close;
+	}
+
+	err = setup_irqs(mc_dev);
+	if (err) {
+		err = -EFAULT;
+		goto err_close;
+	}
+
+#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
+	/* OPTIONAL, register netdev just to make it visible to the user */
+	netdev->netdev_ops = &dpaa2_mac_ndo_ops;
+	netdev->ethtool_ops = &dpaa2_mac_ethtool_ops;
+
+	/* phy starts up enabled so netdev should be up too */
+	netdev->flags |= IFF_UP;
+
+	err = register_netdev(priv->netdev);
+	if (err < 0) {
+		dev_err(dev, "register_netdev error %d\n", err);
+		err = -ENODEV;
+		goto err_free_irq;
+	}
+#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
+
+	/* probe the PHY as a fixed-link if the link type declared in DPC
+	 * explicitly mandates this
+	 */
+	if (priv->attr.link_type == DPMAC_LINK_TYPE_FIXED)
+		goto probe_fixed_link;
+
+	if (priv->attr.eth_if < ARRAY_SIZE(dpaa2_mac_iface_mode)) {
+		if_mode = dpaa2_mac_iface_mode[priv->attr.eth_if];
+		dev_dbg(dev, "\tusing if mode %s for eth_if %d\n",
+			phy_modes(if_mode), priv->attr.eth_if);
+	} else {
+		dev_warn(dev, "Unexpected interface mode %d, will probe as fixed link\n",
+			 priv->attr.eth_if);
+		goto probe_fixed_link;
+	}
+
+	/* try to connect to the PHY */
+	phy_node = of_parse_phandle(dpmac_node, "phy-handle", 0);
+	if (!phy_node) {
+		if (!phy_node) {
+			dev_err(dev, "dpmac node has no phy-handle property\n");
+			err = -ENODEV;
+			goto err_no_phy;
+		}
+	}
+	netdev->phydev = of_phy_connect(netdev, phy_node,
+					&dpaa2_mac_link_changed, 0, if_mode);
+	if (!netdev->phydev) {
+		/* No need for dev_err(); the kernel's loud enough as it is. */
+		dev_dbg(dev, "Can't of_phy_connect() now.\n");
+		/* We might be waiting for the MDIO MUX to probe, so defer
+		 * our own probing.
+		 */
+		err = -EPROBE_DEFER;
+		goto err_defer;
+	}
+	dev_info(dev, "Connected to %s PHY.\n", phy_modes(if_mode));
+
+probe_fixed_link:
+	if (!netdev->phydev) {
+		struct fixed_phy_status status = {
+			.link = 1,
+			/* fixed-phys don't support 10Gbps speed for now */
+			.speed = 1000,
+			.duplex = 1,
+		};
+
+		/* try to register a fixed link phy */
+		netdev->phydev = fixed_phy_register(PHY_POLL, &status, -1, NULL);
+		if (!netdev->phydev || IS_ERR(netdev->phydev)) {
+			dev_err(dev, "error trying to register fixed PHY\n");
+			/* So we don't crash unregister_netdev() later on */
+			netdev->phydev = NULL;
+			err = -EFAULT;
+			goto err_no_phy;
+		}
+		dev_info(dev, "Registered fixed PHY.\n");
+	}
+
+	/* start PHY state machine */
+#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
+	dpaa2_mac_open(netdev);
+#else /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
+	phy_start(netdev->phydev);
+#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
+	return 0;
+
+err_defer:
+err_no_phy:
+#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
+	unregister_netdev(netdev);
+err_free_irq:
+#endif
+	teardown_irqs(mc_dev);
+err_close:
+	dpmac_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
+err_free_mcp:
+	fsl_mc_portal_free(mc_dev->mc_io);
+err_free_netdev:
+	free_netdev(netdev);
+err_exit:
+	return err;
+}
+
+static int dpaa2_mac_remove(struct fsl_mc_device *mc_dev)
+{
+	struct device		*dev = &mc_dev->dev;
+	struct dpaa2_mac_priv	*priv = dev_get_drvdata(dev);
+
+	unregister_netdev(priv->netdev);
+	teardown_irqs(priv->mc_dev);
+	dpmac_close(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle);
+	fsl_mc_portal_free(priv->mc_dev->mc_io);
+	free_netdev(priv->netdev);
+
+	dev_set_drvdata(dev, NULL);
+	kfree(priv);
+
+	return 0;
+}
+
+static const struct fsl_mc_device_match_id dpaa2_mac_match_id_table[] = {
+	{
+		.vendor = FSL_MC_VENDOR_FREESCALE,
+		.obj_type = "dpmac",
+		.ver_major = DPMAC_VER_MAJOR,
+		.ver_minor = DPMAC_VER_MINOR,
+	},
+	{}
+};
+
+static struct fsl_mc_driver dpaa2_mac_drv = {
+	.driver = {
+		.name		= KBUILD_MODNAME,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= dpaa2_mac_probe,
+	.remove		= dpaa2_mac_remove,
+	.match_id_table = dpaa2_mac_match_id_table,
+};
+
+module_fsl_mc_driver(dpaa2_mac_drv);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DPAA2 PHY proxy interface driver");
